package autogen

import (
	"testing"

	policiesv1beta1 "github.com/kyverno/kyverno/api/policies.kyverno.io/v1beta1"
	"github.com/kyverno/kyverno/pkg/cel/autogen"
	"github.com/stretchr/testify/assert"
	admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var (
	ivpol = &policiesv1beta1.ImageValidatingPolicy{
		ObjectMeta: v1.ObjectMeta{
			Name: "test",
		},
		Spec: policiesv1beta1.ImageValidatingPolicySpec{
			MatchConstraints: &admissionregistrationv1.MatchResources{
				ResourceRules: []admissionregistrationv1.NamedRuleWithOperations{
					{
						RuleWithOperations: admissionregistrationv1.RuleWithOperations{
							Operations: []admissionregistrationv1.OperationType{
								admissionregistrationv1.Create,
								admissionregistrationv1.Update,
							},
							Rule: admissionregistrationv1.Rule{
								APIGroups:   []string{""},
								APIVersions: []string{"v1"},
								Resources:   []string{"pods"},
							},
						},
					},
				},
			},
			MatchImageReferences: []policiesv1beta1.MatchImageReference{
				{
					Glob: "ghcr.io/*",
				},
			},
			ImageExtractors: []policiesv1beta1.ImageExtractor{
				{
					Name:       "containers",
					Expression: "object.spec.containers.map(e, e.image)",
				},
			},
			Attestors: []policiesv1beta1.Attestor{
				{
					Name: "notary",
					Notary: &policiesv1beta1.Notary{
						Certs: &policiesv1beta1.StringOrExpression{
							Value: `-----BEGIN CERTIFICATE----------END CERTIFICATE-----`,
						},
					},
				},
			},
			Attestations: []policiesv1beta1.Attestation{
				{
					Name: "sbom",
					Referrer: &policiesv1beta1.Referrer{
						Type: "sbom/cyclone-dx",
					},
				},
			},
			Validations: []admissionregistrationv1.Validation{
				{
					Expression: "images.bar.map(image, verifyImageSignatures(image, [attestors.notary])).all(e, e > 0)",
					Message:    "failed to verify image with notary cert",
				},
			},
			AutogenConfiguration: &policiesv1beta1.ImageValidatingPolicyAutogenConfiguration{
				PodControllers: &policiesv1beta1.PodControllersGenerationConfiguration{
					Controllers: []string{
						"cronjobs",
					},
				},
			},
		},
	}
)

func Test_AutogenImageVerify(t *testing.T) {
	cronRule := []admissionregistrationv1.NamedRuleWithOperations{
		{
			RuleWithOperations: admissionregistrationv1.RuleWithOperations{
				Operations: []admissionregistrationv1.OperationType{
					admissionregistrationv1.Create,
					admissionregistrationv1.Update,
				},
				Rule: admissionregistrationv1.Rule{
					APIGroups:   []string{"batch"},
					APIVersions: []string{"v1"},
					Resources:   []string{"cronjobs"},
				},
			},
		},
	}
	podctrl := []admissionregistrationv1.NamedRuleWithOperations{
		{
			RuleWithOperations: admissionregistrationv1.RuleWithOperations{
				Operations: []admissionregistrationv1.OperationType{
					admissionregistrationv1.Create,
					admissionregistrationv1.Update,
				},
				Rule: admissionregistrationv1.Rule{
					APIGroups:   []string{"apps"},
					APIVersions: []string{"v1"},
					Resources:   []string{"deployments", "statefulsets"},
				},
			},
		},
	}
	cronimg := []policiesv1beta1.ImageExtractor{
		{
			Name:       "containers",
			Expression: "object.spec.jobTemplate.spec.template.spec.containers.map(e, e.image)",
		},
	}
	podctrlimg := []policiesv1beta1.ImageExtractor{
		{
			Name:       "containers",
			Expression: "object.spec.template.spec.containers.map(e, e.image)",
		},
	}
	autogenerated, err := Autogen(ivpol)
	assert.NoError(t, err)
	assert.Equal(t, 1, len(autogenerated))
	assert.Equal(t, cronRule, autogenerated[autogen.AutogenCronjobs].Spec.MatchConstraints.ResourceRules)
	assert.Equal(t, 1, len(autogenerated[autogen.AutogenCronjobs].Spec.ImageExtractors))
	assert.Equal(t, cronimg, autogenerated[autogen.AutogenCronjobs].Spec.ImageExtractors)
	pol := ivpol.DeepCopy()
	pol.Spec.AutogenConfiguration.PodControllers.Controllers = []string{
		"cronjobs",
		"deployments",
		"statefulsets",
	}
	autogenerated, err = Autogen(pol)
	assert.NoError(t, err)
	assert.Equal(t, 2, len(autogenerated))
	assert.Equal(t, podctrl, autogenerated[autogen.AutogenDefaults].Spec.MatchConstraints.ResourceRules)
	assert.Equal(t, 1, len(autogenerated[autogen.AutogenDefaults].Spec.ImageExtractors))
	assert.Equal(t, podctrlimg, autogenerated[autogen.AutogenDefaults].Spec.ImageExtractors)
	assert.Equal(t, cronRule, autogenerated[autogen.AutogenCronjobs].Spec.MatchConstraints.ResourceRules)
}
